package com.fengshang.wedding.web.controller;

import static com.fengshang.wedding.web.controller.ControllerConstants.SESSION_ATTR_CURRENT_USER;

import java.util.Collection;

import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import com.fengshang.wedding.domain.model.api.IMessage;
import com.fengshang.wedding.domain.model.api.ITopic;
import com.fengshang.wedding.domain.model.api.IUser;
import com.fengshang.wedding.domain.model.api.Message;
import com.fengshang.wedding.domain.model.api.Topic;
import com.fengshang.wedding.domain.model.api.User;
import com.fengshang.wedding.domain.service.api.IMessageManager;
import com.fengshang.wedding.domain.service.api.ITopicManager;
import com.fengshang.wedding.domain.service.api.IUserManager;
import com.fengshang.wedding.domain.service.api.UserNotFoundException;
import com.fengshang.wedding.web.view.JsonView;
/**
 * 
 *@author gembin@gmail.com
 * 
 */
@SessionAttributes({SESSION_ATTR_CURRENT_USER})
@Controller
public class UserServiceController {
    private static Logger logger=Logger.getLogger(UserServiceController.class);
	@Autowired
	private IUserManager userManager;
	@Autowired
	private ITopicManager topicManager;
	@Autowired
	private IMessageManager messageManager;
	@Autowired
	private JsonView jsonView;
	/**
	 * @param user
	 * @return
	 */
	private static boolean isUserValid(User user){
		return !(user==null || user.getName()==null || user.getName().equals(""));
	}
	/**
	 * perform user login
	 * @param user
	 * @param model
	 * @return
	 */
	@RequestMapping(value="/loginUser.do", method = RequestMethod.POST)
	public ModelAndView loginUser(User user,ModelMap model){
		Response response=new Response();
		IUser registeredUser=null;
		String message="";
		if(!isUserValid(user)){
			message="Invalid user login access!!";
			logger.error(message);
			response.setResultCode(Response.RESULT_INVALID);
		}else{
			String userName=user.getName();
			try{
				registeredUser=userManager.findUserByName(userName);
				//user not exists
				if(registeredUser==null){
					response.setResultCode(Response.RESULT_NONE);
					message="User "+userName+" not exists!";
					logger.warn(message);
				}else{
					//password is correct
					if(registeredUser.getPassword().equals(user.getPassword())){
						response.setResultCode(Response.RESULT_OK);
						message="User "+userName+" login success!!";
						logger.info(message);
					}else{
						//password is wrong
						response.setResultCode(Response.RESULT_ERROR);
						message="User "+userName+" password is not correct!";
						logger.error(message);
					}
				}
			}catch(Exception e){
				//user not exists
				message="Find user failed:"+e.getMessage();
				logger.error(message);
				response.setResultCode(Response.RESULT_NONE);
			}
		}
		response.setResultMessage(message);
		jsonView.setDataType(JsonView.TYPE_SINGLE_OBJECT);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.RESPONSE,response);
		mav.addObject(JsonView.MODEL,registeredUser);
		//avoid spring check attribute should not be NULL
		model.addAttribute(SESSION_ATTR_CURRENT_USER,registeredUser==null?"":registeredUser);
		return mav;
	}
	
	/**
	 * perform user logout
	 * @param user
	 * @param model
	 * @return
	 */
	@RequestMapping(value="/logoutUser.do", method = RequestMethod.POST)
	public ModelAndView logoutUser(/*User user,*/@ModelAttribute("currUser") User user,HttpSession session){
		Response response=new Response();
		IUser registeredUser=null;
		String message="";
		if(!isUserValid(user)){
			message="Invalid user login access!!";
			logger.error(message);
			response.setResultCode(Response.RESULT_INVALID);
		}else{
			try{
				registeredUser=userManager.findUserByName(user.getName());
				if(registeredUser==null){
					response.setResultCode(Response.RESULT_NONE);
					message="User "+user.getName()+" not exists,cannot perform logout!";
					logger.warn(message);
				}else{
					session.removeAttribute(SESSION_ATTR_CURRENT_USER);
					//Object isUserValid=model.remove(SESSION_ATTR_IS_USER_VALID);
					message="User "+user.getName()+" successfully logout!";
					//logger.debug("Remove key "+SESSION_ATTR_IS_USER_VALID+" from session:"+isUserValid);
					logger.info(message);
				}
			}catch(Exception e){
				message="Find user failed:"+e.getMessage();
				logger.error(message);
				response.setResultCode(Response.RESULT_NONE);
			}
		}
		response.setResultMessage(message);
		jsonView.setDataType(JsonView.TYPE_SINGLE_OBJECT);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.RESPONSE,response);
		return mav;
	}
	
	
	/**
	 * perform create a new user
	 * @param user
	 * @param model
	 * @return
	 */
	@RequestMapping(value="/createUser.do", method = RequestMethod.POST)
	public ModelAndView createUser(User user,ModelMap model) {
		Response response=new Response();
		IUser registeredUser=null;
		String message="";
		if(!isUserValid(user)){
			message="Invalid user,cannot create user!!";
			logger.error(message);
			response.setResultCode(Response.RESULT_INVALID);
		}else{
			logger.debug("create user: "+user);
			try{
				userManager.createUser(user);
				//Chinese character cannot find  FIXME
				registeredUser=userManager.findUserByName(user.getName());
				message="User "+user.getName()+" is successfuly created!";
				logger.info(message);
				response.setResultCode(Response.RESULT_OK);
			}catch(Exception e){
				if(e instanceof UserNotFoundException){
					message="User is created, but cannot retrieve user info:"+e.getMessage();
				}else{
					message="User creation failed:"+e.getMessage();
				}
				logger.error(message);
				response.setResultCode(Response.RESULT_ERROR);
			}
		}
		response.setResultMessage(message);
		jsonView.setDataType(JsonView.TYPE_SINGLE_OBJECT);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,registeredUser);
		mav.addObject(JsonView.RESPONSE,response);
		//login by default, once user is created
		model.addAttribute(SESSION_ATTR_CURRENT_USER,registeredUser==null?"":registeredUser);
		return mav;
	}
	
	/**
	 * 
	 * @param user
	 * @param model
	 * @return
	 */
	@RequestMapping(value="/updateUser.do", method = RequestMethod.POST)
	public ModelAndView updateUser(User user,ModelMap model) {
		Response response=new Response();
		IUser registeredUser=null;
		String message="";
		if(!isUserValid(user)){
			message="Invalid user,cannot update user!!";
			logger.error(message);
			response.setResultCode(Response.RESULT_INVALID);
		}else{
			int id=user.getId();
			logger.debug("find user with id="+id);
			try{
			   registeredUser=userManager.updateUser(user);
			   message="User update success!";
			   response.setResultCode(Response.RESULT_OK);
			   logger.info(message);
			}catch(Exception e){
				message="User update failed:"+e.getMessage();
				logger.error(message);
				response.setResultCode(Response.RESULT_ERROR);
			}
		}
		response.setResultMessage(message);
		jsonView.setDataType(JsonView.TYPE_SINGLE_OBJECT);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,registeredUser);
		mav.addObject(JsonView.RESPONSE,response);
		model.addAttribute(SESSION_ATTR_CURRENT_USER,registeredUser==null?"":registeredUser);
		return mav;
	}
	/**
	 * @param user
	 * @param newPassword
	 * @param model
	 * @return
	 */
	@RequestMapping(value="/updateUserPassword.do", method = RequestMethod.POST)
	public ModelAndView updateUserPassword(User user,String newPassword,ModelMap model){
		Response response=new Response();
		IUser registeredUser=null;
		String message="";
		if(null==user){
			message="Invalid user,cannot update user!!";
			logger.error(message);
			response.setResultCode(Response.RESULT_INVALID);
		}else{
			int id=user.getId();
			String password=user.getPassword();
			logger.debug("find user with id="+id);
			try{
			   registeredUser=userManager.findUserById(id);
			   if(registeredUser.getPassword().equals(password)){
				   user.setPassword(newPassword);
				   logger.debug("User's new password:"+newPassword);
				   registeredUser=userManager.updateUser(user);
				   message="User update password success!";
				   response.setResultCode(Response.RESULT_OK);
				   logger.info(message);
			   }else{
				   registeredUser=null;
				   message="user password is not correct!";
				   response.setResultCode(Response.RESULT_ERROR);
				   logger.warn(message);
			   }
			}catch(Exception e){
				message="User update password failed:"+e.getMessage();
				logger.error(message);
				response.setResultCode(Response.RESULT_ERROR);
				registeredUser=null;
			}
		}
		response.setResultMessage(message);
		jsonView.setDataType(JsonView.TYPE_SINGLE_OBJECT);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,registeredUser);
		mav.addObject(JsonView.RESPONSE,response);
		return mav;
	}
	/**
	 * @param username
	 * @param model
	 * @return
	 */
	@RequestMapping(value="/checkUserAvailable.do", method = RequestMethod.POST)
	public ModelAndView checkUserAvailable(String username){
		Response response=new Response();
		String message="";
		response.setResultCode(Response.RESULT_INVALID);
		if(username!=null && !username.equals("")){
			logger.debug("checking... if user with name="+username+" exists!");
			try{
				userManager.findUserByName(username);
				response.setResultCode(Response.RESULT_ERROR);
				message="your username is already registered!";
				logger.warn(message);
			}catch(UserNotFoundException e){
				//this username is OK for register
				message="your username is valid!";
				logger.info(message);
				response.setResultCode(Response.RESULT_OK);
			}
		}
		response.setResultMessage(message);
		jsonView.setDataType(JsonView.TYPE_SINGLE_OBJECT);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.RESPONSE,response);
		return mav;
	}
	
	
	
	
	/**
	 * create user by Admin
	 * @param user
	 * @return
	 */
	//@RolesAllowed(value = { "" }) TODO
	@RequestMapping(value="/createUserByAdmin.do", method = RequestMethod.POST)
	public ModelAndView createUserByAdmin(User user) {
		Response response=new Response();
		Collection<IUser> users=null;
		String message="";
		if(!isUserValid(user)){
			message="Invalid user,cannot create user!!";
			logger.error(message);
			response.setResultCode(Response.RESULT_INVALID);
		}
		logger.debug("create user: "+user);
		try{
			userManager.createUser(user);
			message="User "+user.getName()+" is successfuly created!";
			response.setResultCode(Response.RESULT_OK);
			users=userManager.findUsersByPagination("select u from User u where u.role=2", 0, 1); 
			logger.info("Get "+users.size()+" users!");
		}catch(Exception e){
			message="User creation failed:"+e.getMessage();
			logger.error(message);
			response.setResultCode(Response.RESULT_ERROR);
		}
	 
		response.setResultMessage(message);
		jsonView.setDataType(JsonView.TYPE_COLLECTION_OBJECT);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,users);
		mav.addObject(JsonView.RESPONSE,response);
		return mav;
	}
	
	
	
	
	
	
	
	
	@RequestMapping(value="/findAllUsers.do")
	public ModelAndView findAllUsers(
			int page,
			String sortname,
			String sortorder,
			String query,
			String name, //search name
			String qtype,// 
			@RequestParam("rp")int pageSize, ModelMap modelMap){
		logger.debug("page="+page); //page
		logger.debug("sortname="+sortname);
		logger.debug("sortorder="+sortorder);
		logger.debug("query="+query);
		logger.debug("name="+name);
		logger.debug("rp="+pageSize);//pageSize
		logger.debug("modelMap="+modelMap);
		Response response=new Response();
		String q="SELECT u FROM User u ORDER BY u."+sortname+" "+sortorder;
		logger.debug("Query="+q);
		Collection<IUser> users=userManager.findUsersByPagination(q,pageSize, page); 
		logger.debug("Users:"+users.size());
		response.setResultCode(Response.RESULT_OK);
		response.setResultMessage("Find "+users.size()+" Users!");
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,users);
		mav.addObject(JsonView.TOTAL, userManager.getTotalRecords());
		mav.addObject(JsonView.PAGE,new Integer(page));
		mav.addObject(JsonView.RESPONSE,response);
		modelMap.addAttribute("a","av");
		return mav;
	}
	
	/**
	 * 
	 * @param user
	 * @return
	 */
	@RequestMapping(value="/createGuest.do", method = RequestMethod.POST)
	public ModelAndView createGuest(User user) {
		if(user==null || user.getName()==null || user.getName().equals(""))return null;
		logger.info("create guest:%s"+ user);
		userManager.createGuest(user);
		Collection<IUser> users=userManager.findUsersByPagination("select u from User u where u.role=1", 0, 1); 
		logger.info(users.toString());
		logger.info(""+users.size());
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,users);
		return mav;
	}
	/**
	 * Required:
	 * title
	 * content
	 * 
	 * @param userId
	 * @param topic
	 * @return
	 */
	@RequestMapping(value="/createTopic.do",method = RequestMethod.POST)
	public ModelAndView createTopic(int userId,Topic topic){
		System.out.println(userId); 
		topicManager.createTopic(userId, topic);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,topic);
		return mav;
	}
	/**
	 * Required:
	 * title
	 * content
	 * 
	 * @param topicId
	 * @param message
	 * @return
	 */
	@RequestMapping(value="/createMessage.do",method = RequestMethod.POST)
	public ModelAndView createMessage(int topicId,Message message){
		System.out.println(topicId); 
		messageManager.createMessage(topicId, message);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,message);
		return mav;
	}
	
	/**
	 * 
	 * @param topicId
	 * @return
	 */
	@RequestMapping(value="/getMessages.do",method = RequestMethod.POST)
	public ModelAndView getMessages(int topicId){
		//TODO select by topicId
		Collection<IMessage> messages=messageManager.findTopicMessagesByPagination(topicId, 0, 1);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,messages);
		return mav;
	}

	/**
	 * 
	 * @param userId
	 * @return
	 */
	@RequestMapping(value="/getTopics.do",method = RequestMethod.POST)
	public ModelAndView getTopics(int userId){
		Collection<ITopic> topics=topicManager.findUserTopicsByPagination(userId, 0, 1);
		ModelAndView mav = new ModelAndView(jsonView);
		mav.addObject(JsonView.MODEL,topics);
		return mav;
	}
	
	
	//*****************************************************************************************//
	
	@ModelAttribute("hello")
	public String getHello() {
		return "hello_gggg";
	}
	
	@RequestMapping(params = "method=login")
	public ModelAndView login(@RequestParam("id") long userId) {
		System.out.println("test:"+userId);
		return new ModelAndView("OK");
	}

}
